package com.haizhi.crm.sys.shiro;

import com.haizhi.crm.common.context.Resource;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisClusterManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.LinkedHashMap;

/**
 * Created by chengmo on 2018/7/2.
 */
@Configuration
public class ShiroConfig {

    @Value("${spring.redis.cluster.nodes:}" )
    private String redisHost;
    @Value("${server.session.timeout:1800}" )
    private int timeout;// seconds
    @Value("${server.port:8080}" )
    private int port;// seconds

    @Bean
    public RedisCacheManager redisCacheManager() {
        RedisCacheManager redisCacheManager = new RedisCacheManager();
        redisCacheManager.setRedisManager(redisManager());
        return redisCacheManager;
    }

    @Bean
    public RedisClusterManager redisManager() {
        RedisClusterManager redisManager = new RedisClusterManager();
        redisManager.setHost(redisHost);
        //redisManager.setPassword(password);
        return redisManager;
    }

    @Bean
    public RedisSessionDAO redisSessionDAO() {
        RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
        redisSessionDAO.setRedisManager(redisManager());
        redisSessionDAO.setExpire(timeout);
        String prefix = redisSessionDAO.getKeyPrefix();
        prefix = prefix + Resource.getIP() + ":" + port + ":";
        redisSessionDAO.setKeyPrefix(prefix);
        return redisSessionDAO;
    }

    @Bean
    public ChainDefinitionProvider chainDefinitionProvider() {
        return new ChainDefinitionProvider();
    }

    @Bean
    public UserRealm userRealm() {
        return new UserRealm(new UserCredentialsMatcher());
    }

    @Bean
    public DefaultWebSessionManager sessionManager() {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setDeleteInvalidSessions(true);
        sessionManager.setSessionDAO(redisSessionDAO());
        sessionManager.setCacheManager(redisCacheManager());
        sessionManager.setGlobalSessionTimeout(timeout * 1000);// milliseconds
        return sessionManager;
    }

    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(userRealm());
        securityManager.setSessionManager(sessionManager());
        securityManager.setCacheManager(redisCacheManager());
        securityManager.setRememberMeManager(cookieRememberMeManager());
        return securityManager;
    }

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        bean.setSecurityManager(securityManager);
        LinkedHashMap<String, Filter> filters = new LinkedHashMap<>();

        filters.put("cookie", cookieFilter());
        filters.put("roles", new UserRolesAuthorizationFilter());

        bean.setFilters(filters);

        bean.setLoginUrl("/auth/unauth" );
        bean.setSuccessUrl("/index" );
        bean.setUnauthorizedUrl("/auth/unauth" );

        bean.setFilterChainDefinitionMap(chainDefinitionProvider().getAllRolesPermissions());
        return bean;
    }

    @Bean
    public FormAuthenticationFilter cookieFilter() {
        FormAuthenticationFilter filter = new FormAuthenticationFilter();
        filter.setRememberMeParam("haizhi-crm" );
        return filter;
    }

    @Bean
    public SimpleCookie simpleCookie() {
        SimpleCookie cookie = new SimpleCookie();
        cookie.setHttpOnly(true);
        cookie.setMaxAge(43200);// 12hours
        cookie.setName("haizhi-crm" );
        cookie.setPath("/" );
        return cookie;
    }

    @Bean
    public CookieRememberMeManager cookieRememberMeManager() {
        CookieRememberMeManager manager = new CookieRememberMeManager();
        manager.setCookie(simpleCookie());
        //manager.setCipherKey(Base64.decode("2AvVhdsgUs0FSA3SDFAdag=="));
        return manager;
    }
}
